import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.File;
import java.io.IOException;


/**
 * Created by Shine Kaye on 2016/10/21.
 */
public class ResizeImageUtils {

    /**
     * Zoom in (enlarge) an image by Bilinear Interpolation
     *
     * @param srcImage: Path of the source image
     * @param resultImage: Path of the after-shrink image
     * @param k1: Enlarging scale of height
     * @param k2: Enlarging scale of weight
     * @throws IOException
     */
    public static void enlarge(String srcImage, String resultImage, float k1, float k2) throws IOException {
        if(k1 <1 || k2<1) {
            System.err.println("This is Enlarge image funcation, please set k1<=1 and k2<=1！");

        }
        BufferedImage image = ImageIO.read(new File(srcImage));
        int height = image.getHeight();
        int width = image.getWidth();
        int[] imageArray = new int[height*width];
        image.getRGB(0, 0, width, height, imageArray, 0, width);
        
        float ii = 1/k1;
        float jj = (1/k2);
        int dd = (int)(ii*jj);
        int imageType = image.getType();
        int w = image.getWidth();
        int h = image.getHeight();
        int m = Math.round(k1*w);
        int n = Math.round(k2*h);
        int[] pix = new int[w*h];
        pix = image.getRGB(0, 0, w, h, pix, 0, w);
        int[] newpix = new int[m*n];

        for(int j=0; j<h-1; j++){
            for(int i=0; i<w-1; i++) {
                int x0 = Math.round(i*k1);
                int y0 = Math.round(j*k2);
                int x1, y1;
                if(i == w-2) {
                    x1 = m-1;
                } else {
                    x1 = Math.round((i+1)*k1);
                }
                if(j == h-2) {
                    y1 = n-1;
                } else {
                    y1 = Math.round((j+1)*k2);
                }
                int d1 = x1 - x0;
                int d2 = y1 - y0;
                if(0 == newpix[y0*m + x0]) {
                    newpix[y0*m + x0] =  pix[j*w+i];
                }
                if(0 == newpix[y0*m + x1]) {
                    if(i == w-2) {
                        newpix[y0*m + x1] = pix[j*w+w-1];
                    } else {
                        newpix[y0*m + x1] =  pix[j*w+i+1];
                    }
                }
                if(0 == newpix[y1*m + x0]){
                    if(j == h-2) {
                        newpix[y1*m + x0] = pix[(h-1)*w+i];
                    } else {
                        newpix[y1*m + x0] =  pix[(j+1)*w+i];
                    }
                }
                if(0 == newpix[y1*m + x1]) {
                    if(i==w-2 && j==h-2) {
                        newpix[y1*m + x1] = pix[(h-1)*w+w-1];
                    } else {
                        newpix[y1*m + x1] = pix[(j+1)*w+i+1];
                    }
                }
                int r, g, b;
                float c;
                ColorModel cm = ColorModel.getRGBdefault();
                for(int l=0; l<d2; l++) {
                    for(int k=0; k<d1; k++) {
                        if(0 == l) {
                            if(j<h-1 && newpix[y0*m + x0 + k] == 0) {
                                c = (float)k/d1;
                                r = cm.getRed(newpix[y0*m + x0]) + (int)(c*(cm.getRed(newpix[y0*m + x1]) - cm.getRed(newpix[y0*m + x0])));//newpix[(y0+l)*m + k]
                                g = cm.getGreen(newpix[y0*m + x0]) + (int)(c*(cm.getGreen(newpix[y0*m + x1]) - cm.getGreen(newpix[y0*m + x0])));
                                b = cm.getBlue(newpix[y0*m + x0]) + (int)(c*(cm.getBlue(newpix[y0*m + x1]) - cm.getBlue(newpix[y0*m + x0])));
                                newpix[y0*m + x0 + k] = new Color(r,g,b).getRGB();
                            }
                            if(j+1<h && newpix[y1*m + x0 + k] == 0) {
                                c = (float)k/d1;
                                r = cm.getRed(newpix[y1*m + x0]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y1*m + x0])));
                                g = cm.getGreen(newpix[y1*m + x0]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y1*m + x0])));
                                b = cm.getBlue(newpix[y1*m + x0]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y1*m + x0])));
                                newpix[y1*m + x0 + k] = new Color(r,g,b).getRGB();
                            }
                        } else {
                            c = (float)l/d2;
                            r = cm.getRed(newpix[y0*m + x0+k]) + (int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k])));
                            g = cm.getGreen(newpix[y0*m + x0+k]) + (int)(c*(cm.getGreen(newpix[y1*m + x0+k]) - cm.getGreen(newpix[y0*m + x0+k])));
                            b = cm.getBlue(newpix[y0*m + x0+k]) + (int)(c*(cm.getBlue(newpix[y1*m + x0+k]) - cm.getBlue(newpix[y0*m + x0+k])));
                            newpix[(y0+l)*m + x0 + k] = new Color(r,g,b).getRGB();
                        }
                    }
                    if(i==w-2 || l==d2-1) {
                        c = (float)l/d2;
                        r = cm.getRed(newpix[y0*m + x1]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y0*m + x1])));
                        g = cm.getGreen(newpix[y0*m + x1]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y0*m + x1])));
                        b = cm.getBlue(newpix[y0*m + x1]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y0*m + x1])));
                        newpix[(y0+l)*m + x1] = new Color(r,g,b).getRGB();
                    }
                }
            }
        }

        BufferedImage imageOut = new BufferedImage( m, n, imageType);
        imageOut.setRGB(0, 0, m, n, newpix, 0, m);

        String fileName = (new File(srcImage.trim())).getName();
        File file = new File(resultImage + "afterEnlarge" + fileName);
        ImageIO.write(imageOut, "jpg", file);
        
    }

    /**
     * Zoom out (shrink) an image.
     *
     * @param srcImage: Path of the source image
     * @param resultImage: Path of the after-shrink image
     * @param k1: Shrinking scale of height
     * @param k2: Shrinking scale of weight
     * @throws IOException
     */
    public static void shrink(String srcImage, String resultImage, float k1, float k2) throws IOException {

        if(k1>1 || k2>1) {
            System.err.println("This is Shrink image funcation, please set k1>=1 and k2>=1！");
        }

        BufferedImage image = ImageIO.read(new File(srcImage));
        int height = image.getHeight();
        int width = image.getWidth();

        int tarHeight = (int)(height*k1);
        int tarWidth = (int)(width*k2);

        BufferedImage newImage = new BufferedImage(tarWidth, tarHeight, BufferedImage.TYPE_INT_RGB);
        newImage.getGraphics().drawImage(image.getScaledInstance(tarWidth, tarHeight, Image.SCALE_SMOOTH), 0, 0, null);

        String fileName = (new File(srcImage.trim())).getName();
        File file = new File(resultImage + "/afterShrink" + fileName);
        ImageIO.write(newImage, "jpg", file);
    }
}
